#include "mainwindow.h"
#include "./ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    timer = new QTimer(this);
    on_Button_refresh_clicked();
    on_Button_init_pose_clicked();
    LCD_angles_show();
    qDebug() << "调试开始2！！！";
    // 连接滑动条 valueChanged 信号到 LCD 显示
    // 连接信号和槽
    connect(timer, &QTimer::timeout, this, &MainWindow::timer_send_data);

    connect(ui->horizontalSlider_1, &QSlider::valueChanged,
            ui->lcdNumber_1, static_cast<void (QLCDNumber::*)(int)>(&QLCDNumber::display));
    connect(ui->horizontalSlider_2, &QSlider::valueChanged,
            ui->lcdNumber_2, static_cast<void (QLCDNumber::*)(int)>(&QLCDNumber::display));
    connect(ui->horizontalSlider_3, &QSlider::valueChanged,
            ui->lcdNumber_3, static_cast<void (QLCDNumber::*)(int)>(&QLCDNumber::display));
    connect(ui->horizontalSlider_4, &QSlider::valueChanged,
            ui->lcdNumber_4, static_cast<void (QLCDNumber::*)(int)>(&QLCDNumber::display));
    connect(ui->horizontalSlider_5, &QSlider::valueChanged,
            ui->lcdNumber_5, static_cast<void (QLCDNumber::*)(int)>(&QLCDNumber::display));
    connect(ui->horizontalSlider_6, &QSlider::valueChanged,
            ui->lcdNumber_6, static_cast<void (QLCDNumber::*)(int)>(&QLCDNumber::display));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_Button_init_pose_clicked()
{
    //45 30 -90 -30 0
    ui->lineEdit_grip_x->setText("131.947922");
    ui->lineEdit_grip_y->setText("131.947922");
    ui->lineEdit_grip_z->setText("119.282032");

    //135 60 -90 -60 0
    ui->lineEdit_release_x->setText("-85.360494");
    ui->lineEdit_release_y->setText("85.360494");
    ui->lineEdit_release_z->setText("126.602540");
}


void MainWindow::on_Button_refresh_clicked()
{
    ui->comboBox_ports->clear();//清空串口号
    const auto ports = QSerialPortInfo::availablePorts();
    foreach (const QSerialPortInfo &Info,QSerialPortInfo::availablePorts())
    {
        ui->comboBox_ports->addItem(Info.portName());
    }
    qDebug() << "检测到串口数量：" << ports.size();

    if(ports.size() == 0)
    {
        ui->label_message->setText("无可用串口");
    }
}


void MainWindow::on_Button_link_serial_clicked()
{
    //设置端口
    my_Serial.setPortName(ui->comboBox_ports->currentText());
    my_Serial.setBaudRate(ui->comboBox_baudrate->currentText().toInt());
    //打开串口
    my_Serial.open(QIODevice::ReadWrite);

    //设置校验位
    switch(ui->comboBox_paritybit->currentIndex())
    {
    case 0:
        my_Serial.setParity(QSerialPort::NoParity);

        break;
    case 1:
        my_Serial.setParity(QSerialPort::OddParity);
        break;
    case 2:
        my_Serial.setParity(QSerialPort::EvenParity);
        break;
    }
    //设置数据位
    switch(ui->comboBox_databit->currentText().toInt())
    {
    case 8:
        my_Serial.setDataBits(QSerialPort::Data8);
        break;
    case 7:
        my_Serial.setDataBits(QSerialPort::Data7);
        break;
    case 6:
        my_Serial.setDataBits(QSerialPort::Data6);
        break;
    case 5:
        my_Serial.setDataBits(QSerialPort::Data5);
        break;
    }
    //设置停止位
    switch(ui->comboBox_stopbit->currentIndex())
    {
    case 0:
        my_Serial.setStopBits(QSerialPort::OneStop);
        break;
    case 1:
        my_Serial.setStopBits(QSerialPort::OneAndHalfStop);
        break;
    case 2:
        my_Serial.setStopBits(QSerialPort::TwoStop);
        break;
    }

    if(my_Serial.isOpen())
    {
        connect(&my_Serial,&QSerialPort::readyRead,this,&MainWindow::message_Recevied);
        ui->label_message->setStyleSheet("color:red;");
        ui->label_message->setText("串口连接成功");
        ui->comboBox_ports->setDisabled(true);
        ui->comboBox_baudrate->setDisabled(true);
        ui->comboBox_databit->setDisabled(true);
        ui->comboBox_paritybit->setDisabled(true);
        ui->comboBox_stopbit->setDisabled(true);

    }
}


void MainWindow::on_Button_dis_serial_clicked()
{
    my_Serial.close();
    if(my_Serial.isOpen())
    {
        ui->label_message->setText("串口关闭失败");
    }
    else
    {
        ui->label_message->setText("串口未连接");
        ui->label_message->setStyleSheet("color:white;");
        ui->comboBox_ports->setEnabled(true);
        ui->comboBox_baudrate->setEnabled(true);
        ui->comboBox_databit->setEnabled(true);
        ui->comboBox_paritybit->setEnabled(true);
        ui->comboBox_stopbit->setEnabled(true);
    }
}

// 辅助函数：安全更新滑动条
void MainWindow::UpdateSliderValue(QSlider* slider, int value)
{
    slider->blockSignals(true);
    slider->setValue(value);
    slider->blockSignals(false);
}

void MainWindow::on_Button_clear_rx_clicked()
{
    ui->textEdit_rx->clear();
    this->rx_num=0;
    ui->label_rx_num->setText("");
}

/*
 * 数据分片问题：

原因：串口数据可能不是一次性完整接收的，而是分多次接收的（比如先收到部分数据，再收到剩余数据）。

验证：在 message_Recevied() 函数开头打印 buf.size()，观察每次接收到的数据长度。

解决：需要实现一个缓冲区，将多次接收的数据拼接起来，直到完整的一帧（49字节）到达后再解析。

缓冲区未拼接：

原因：QSerialPort::readAll() 每次只返回当前可用的数据，可能不完整。

解决：维护一个全局或成员变量的缓冲区，将每次接收的数据追加进去，然后检查是否满足帧长度和帧头条件

 */
void MainWindow::message_Recevied()
{
    QByteArray buf = my_Serial.readAll();
    this->rx_num += buf.size();

    // HEX模式显示原始数据
    if (ui->comboBox_rxformat->currentText() == "HEX") {
        QString hexStr;
        for (int i = 0; i < buf.size(); i++) {
            hexStr += QString("%1 ").arg(static_cast<quint8>(buf[i]), 2, 16, QChar('0')).toUpper();
        }
        ui->textEdit_rx->insertPlainText(hexStr + "\n");
    } else {
        ui->textEdit_rx->insertPlainText(buf);
    }
    ui->textEdit_rx->moveCursor(QTextCursor::End);

    ui->textEdit_rx->setLineWrapMode(QTextEdit::NoWrap);  // 禁止自动换行
    // 追加到缓冲区
    m_rxBuffer.append(buf);

    // 检查缓冲区是否足够长
    while (m_rxBuffer.size() >= 49) {
        // 查找帧头0x5A
        int frameStart = m_rxBuffer.indexOf(0x5A);
        if (frameStart == -1) {
            // 没有找到帧头，丢弃所有数据
            m_rxBuffer.clear();
            break;
        }

        // 丢弃帧头之前的数据
        if (frameStart > 0) {
            m_rxBuffer.remove(0, frameStart);
        }

        // 检查剩余数据是否足够一帧
        if (m_rxBuffer.size() >= 49) {
            QByteArray frame = m_rxBuffer.left(49);
            m_rxBuffer.remove(0, 49);

            // 解析数据帧
            double angles[6];
            memcpy(angles, frame.constData() + 1, sizeof(double) * 6);

            // 打印解码后的数据
            QString decodedStr = "Decoded Angles:\n";
            for (int i = 0; i < 6; i++) {
                decodedStr += QString("Angle %1: %2\n").arg(i + 1).arg(angles[i], 0, 'f', 1);
            }
            ui->textEdit_rx->insertPlainText(decodedStr);

            for(int i=0;i < 6 ;i++)
            {
                now_angles[i] = angles[i];
                angles_init[i] = angles[i];
            }
            // 更新LCD显示（整数）
            ui->lcdNumber_1->display(now_angles[0]);
            ui->lcdNumber_2->display(now_angles[1]);
            ui->lcdNumber_3->display(now_angles[2]);
            ui->lcdNumber_4->display(now_angles[3]);
            ui->lcdNumber_5->display(now_angles[4]);
            ui->lcdNumber_6->display(now_angles[5]);

            // 更新滑动条（整数）
            UpdateSliderValue(ui->horizontalSlider_1, now_angles[0]);
            UpdateSliderValue(ui->horizontalSlider_2, now_angles[1]);
            UpdateSliderValue(ui->horizontalSlider_3, now_angles[2]);
            UpdateSliderValue(ui->horizontalSlider_4, now_angles[3]);
            UpdateSliderValue(ui->horizontalSlider_5, now_angles[4]);
            UpdateSliderValue(ui->horizontalSlider_6, now_angles[5]);
        }
    }

    ui->label_rx_num->setText(QString::number(this->rx_num));
}


void MainWindow::on_Button_serial_send_clicked()
{
    if (ui->comboBox_txformat->currentText() == "HEX")
    {
        this->tx_mode = 0;
        qDebug() << "hex模式";
    }
    else // 文本模式
    {
        this->tx_mode = 1;
        qDebug() << "文本模式";
    }

    if (my_Serial.isOpen())
    {
        if (this->tx_mode == 0) // hex发送
        {
            // 将用户输入的十六进制字符串转换为字节数组
            QByteArray data = QByteArray::fromHex(ui->textEdit_tx->
                                                  toPlainText().toLatin1());
            this->tx_num += my_Serial.write(data);
        }
        else // 文本发送
        {
            // 直接发送用户输入的文本
            QByteArray data = ui->textEdit_tx->toPlainText().toLatin1();
            this->tx_num += my_Serial.write(data);
        }

        ui->label_tx_num->setText(QString::number(this->tx_num));
        qDebug() << "发送成功";
    }
    else
    {
        qDebug() << "串口未打开";
    }
}


void MainWindow::on_Button_send_pose_clicked()
{
    // 1. 检查串口是否打开
    if (!my_Serial.isOpen()) {
        QMessageBox::warning(this, "错误", "串口未打开");
        return;
    }

    // 2. 获取三个抓取坐标值和释放坐标值并转换为浮点数
    bool grip_x, grip_y, grip_z, release_x ,release_y ,release_z;

    double g_x = ui->lineEdit_grip_x->text().toDouble(&grip_x);
    double g_y = ui->lineEdit_grip_y->text().toDouble(&grip_y);
    double g_z = ui->lineEdit_grip_z->text().toDouble(&grip_z);

    double r_x = ui->lineEdit_release_x->text().toDouble(&release_x);
    double r_y = ui->lineEdit_release_y->text().toDouble(&release_y);
    double r_z = ui->lineEdit_release_z->text().toDouble(&release_z);

    // 3. 验证输入有效性
    if (!grip_x || !grip_y || !grip_z ||!release_x ||!release_y ||!release_z) {
        QMessageBox::warning(this, "错误", "请输入有效的浮点数");
        return;
    }

    // 4. 构造数据帧
    QByteArray data;
    data.append(0xA5);  // 抓取释放帧头

    // 添加三个浮点数（小端格式）
    data.append(reinterpret_cast<const char*>(&g_x), sizeof(g_x));
    data.append(reinterpret_cast<const char*>(&g_y), sizeof(g_y));
    data.append(reinterpret_cast<const char*>(&g_z), sizeof(g_z));
    data.append(reinterpret_cast<const char*>(&r_x), sizeof(r_x));
    data.append(reinterpret_cast<const char*>(&r_y), sizeof(r_y));
    data.append(reinterpret_cast<const char*>(&r_z), sizeof(r_z));


    // 5. 发送数据
    qint64 bytesWritten = my_Serial.write(data);

    // 6. 检查发送结果
    if (bytesWritten == -1) {
        QMessageBox::warning(this, "错误", "发送失败: " + my_Serial.errorString());
    }
    else if (bytesWritten != data.size())
    {
        QMessageBox::warning(this, "警告",
                             QString("数据未完全发送，已发送 %1/%2 字节")
                                 .arg(bytesWritten).arg(data.size()));
    } else {
        qDebug() << "成功发送抓取坐标数据  X:" << g_x << "Y:" << g_y << "Z:" << g_z;
        qDebug() << "成功发送释放坐标数据  X:" << r_x << "Y:" << r_y << "Z:" << r_z;
    }

}


void MainWindow::on_Button_clear_pose_clicked()
{
    ui->lineEdit_grip_x->setText("0");
    ui->lineEdit_grip_y->setText("0");
    ui->lineEdit_grip_z->setText("0");
    ui->lineEdit_release_x->setText("0");
    ui->lineEdit_release_y->setText("0");
    ui->lineEdit_release_z->setText("0");

}


void MainWindow::on_Button_grip_pose_clicked()
{
    // 1. 检查串口是否打开
    if (!my_Serial.isOpen()) {
        QMessageBox::warning(this, "错误", "串口未打开");
        return;
    }

    // 2. 获取三个抓取坐标值和释放坐标值并转换为浮点数
    bool grip_x, grip_y, grip_z;

    double g_x = ui->lineEdit_grip_x->text().toDouble(&grip_x);
    double g_y = ui->lineEdit_grip_y->text().toDouble(&grip_y);
    double g_z = ui->lineEdit_grip_z->text().toDouble(&grip_z);

    // 3. 验证输入有效性
    if (!grip_x || !grip_y || !grip_z)
    {
        QMessageBox::warning(this, "错误", "请输入有效的浮点数");
        return;
    }

    // 4. 构造数据帧
    QByteArray data;
    double release_buf[3] = {0xFF,0xFF,0xFF};
    data.append(0xA3);  // 抓取位姿帧头

    // 添加三个浮点数（小端格式）
    data.append(reinterpret_cast<const char*>(&g_x), sizeof(g_x));
    data.append(reinterpret_cast<const char*>(&g_y), sizeof(g_y));
    data.append(reinterpret_cast<const char*>(&g_z), sizeof(g_z));
    data.append(reinterpret_cast<const char*>(release_buf), sizeof(release_buf));

    // 5. 发送数据
    qint64 bytesWritten = my_Serial.write(data);

    // 6. 检查发送结果
    if (bytesWritten == -1) {
        QMessageBox::warning(this, "错误", "发送失败: " + my_Serial.errorString());
    }
    else if (bytesWritten != data.size())
    {
        QMessageBox::warning(this, "警告",
                             QString("数据未完全发送，已发送 %1/%2 字节")
                                 .arg(bytesWritten).arg(data.size()));
    }
    else
    {
        qDebug() << "成功发送抓取坐标数据  X:" << g_x << "Y:" << g_y << "Z:" << g_z;

    }
}



void MainWindow::on_Button_send_angles_clicked()
{
    // 1. 检查串口是否打开
    if (!my_Serial.isOpen()) {
        QMessageBox::warning(this, "错误", "串口未打开");
        return;
    }

    // 2. 获取六个滑动条的值
    double sliderValue1 = ui->horizontalSlider_1->value();
    double sliderValue2 = ui->horizontalSlider_2->value();
    double sliderValue3 = ui->horizontalSlider_3->value();
    double sliderValue4 = ui->horizontalSlider_4->value();
    double sliderValue5 = ui->horizontalSlider_5->value();
    double sliderValue6 = ui->horizontalSlider_6->value();

    // 3. 在对应的LCD上显示数值
    ui->lcdNumber_1->display(sliderValue1);
    ui->lcdNumber_2->display(sliderValue2);
    ui->lcdNumber_3->display(sliderValue3);
    ui->lcdNumber_4->display(sliderValue4);
    ui->lcdNumber_5->display(sliderValue5);
    ui->lcdNumber_6->display(sliderValue6);

    // 4. 构造数据帧
    QByteArray data;
    data.append(0x5A);  // 滑动条数据帧头

    // 添加六个整数值（假设使用小端格式）
    data.append(reinterpret_cast<const char*>(&sliderValue1), sizeof(sliderValue1));
    data.append(reinterpret_cast<const char*>(&sliderValue2), sizeof(sliderValue2));
    data.append(reinterpret_cast<const char*>(&sliderValue3), sizeof(sliderValue3));
    data.append(reinterpret_cast<const char*>(&sliderValue4), sizeof(sliderValue4));
    data.append(reinterpret_cast<const char*>(&sliderValue5), sizeof(sliderValue5));
    data.append(reinterpret_cast<const char*>(&sliderValue6), sizeof(sliderValue6));

    // 5. 发送数据
    qint64 bytesWritten = my_Serial.write(data);

    // 6. 检查发送结果
    if (bytesWritten == -1) {
        QMessageBox::warning(this, "错误", "发送失败: " + my_Serial.errorString());
    }
    else if (bytesWritten != data.size()) {
        QMessageBox::warning(this, "警告",
                             QString("数据未完全发送，已发送 %1/%2 字节")
                                 .arg(bytesWritten).arg(data.size()));
    } else {
        qDebug() << "成功发送滑动条数据: "
                 << sliderValue1 << ", " << sliderValue2 << ", " << sliderValue3
                 << ", " << sliderValue4 << ", " << sliderValue5 << ", " << sliderValue6;
    }
}


void MainWindow::LCD_angles_show()
{
    // 2. 获取六个滑动条的值
    int sliderValue1 = ui->horizontalSlider_1->value();
    int sliderValue2 = ui->horizontalSlider_2->value();
    int sliderValue3 = ui->horizontalSlider_3->value();
    int sliderValue4 = ui->horizontalSlider_4->value();
    int sliderValue5 = ui->horizontalSlider_5->value();
    int sliderValue6 = ui->horizontalSlider_6->value();

    // 3. 在对应的LCD上显示数值
    ui->lcdNumber_1->display(sliderValue1);
    ui->lcdNumber_2->display(sliderValue2);
    ui->lcdNumber_3->display(sliderValue3);
    ui->lcdNumber_4->display(sliderValue4);
    ui->lcdNumber_5->display(sliderValue5);
    ui->lcdNumber_6->display(sliderValue6);
}

void MainWindow::on_Button_init_angles_clicked()
{
    // 设置滑动条值（先阻塞信号避免触发valueChanged）
    ui->horizontalSlider_1->blockSignals(true);
    ui->horizontalSlider_1->setValue(this->angles_init[0]);
    ui->horizontalSlider_1->blockSignals(false);

    ui->horizontalSlider_2->blockSignals(true);
    ui->horizontalSlider_2->setValue(this->angles_init[1]);
    ui->horizontalSlider_2->blockSignals(false);

    ui->horizontalSlider_3->blockSignals(true);
    ui->horizontalSlider_3->setValue(this->angles_init[2]);
    ui->horizontalSlider_3->blockSignals(false);

    ui->horizontalSlider_4->blockSignals(true);
    ui->horizontalSlider_4->setValue(this->angles_init[3]);
    ui->horizontalSlider_4->blockSignals(false);

    ui->horizontalSlider_5->blockSignals(true);
    ui->horizontalSlider_5->setValue(this->angles_init[4]);
    ui->horizontalSlider_5->blockSignals(false);

    ui->horizontalSlider_6->blockSignals(true);
    ui->horizontalSlider_6->setValue(this->angles_init[5]);
    ui->horizontalSlider_6->blockSignals(false);

    // 更新LCD显示
    ui->lcdNumber_1->display(this->angles_init[0]);
    ui->lcdNumber_2->display(this->angles_init[1]);
    ui->lcdNumber_3->display(this->angles_init[2]);
    ui->lcdNumber_4->display(this->angles_init[3]);
    ui->lcdNumber_5->display(this->angles_init[4]);
    ui->lcdNumber_6->display(this->angles_init[5]);
}


void MainWindow::on_Button_re_nowangles_clicked()
{
    // 获取六个滑动条当前的值
    now_angles[0] = ui->horizontalSlider_1->value();
    now_angles[1] = ui->horizontalSlider_2->value();
    now_angles[2] = ui->horizontalSlider_3->value();
    now_angles[3] = ui->horizontalSlider_4->value();
    now_angles[4] = ui->horizontalSlider_5->value();
    now_angles[5] = ui->horizontalSlider_6->value();

}


void MainWindow::on_Button_restore_angles_clicked()
{
    // 设置滑动条值（先阻塞信号避免触发valueChanged）
    ui->horizontalSlider_1->blockSignals(true);
    ui->horizontalSlider_1->setValue(now_angles[0]);
    ui->horizontalSlider_1->blockSignals(false);

    ui->horizontalSlider_2->blockSignals(true);
    ui->horizontalSlider_2->setValue(now_angles[1]);
    ui->horizontalSlider_2->blockSignals(false);

    ui->horizontalSlider_3->blockSignals(true);
    ui->horizontalSlider_3->setValue(now_angles[2]);
    ui->horizontalSlider_3->blockSignals(false);

    ui->horizontalSlider_4->blockSignals(true);
    ui->horizontalSlider_4->setValue(now_angles[3]);
    ui->horizontalSlider_4->blockSignals(false);

    ui->horizontalSlider_5->blockSignals(true);
    ui->horizontalSlider_5->setValue(now_angles[4]);
    ui->horizontalSlider_5->blockSignals(false);

    ui->horizontalSlider_6->blockSignals(true);
    ui->horizontalSlider_6->setValue(now_angles[5]);
    ui->horizontalSlider_6->blockSignals(false);

    // 更新LCD显示
    ui->lcdNumber_1->display(now_angles[0]);
    ui->lcdNumber_2->display(now_angles[1]);
    ui->lcdNumber_3->display(now_angles[2]);
    ui->lcdNumber_4->display(now_angles[3]);
    ui->lcdNumber_5->display(now_angles[4]);
    ui->lcdNumber_6->display(now_angles[5]);
}


void MainWindow::on_checkBox_timer_stateChanged(int state)
{
    if (state == Qt::Checked)
    {
        // 获取时间间隔
        bool ok;
        int timeout = ui->lineEdit_timeout->text().toInt(&ok);
        if (!ok || timeout <= 0)
        {
            QMessageBox::warning(this, "错误", "请输入有效的时间间隔（毫秒）");
            ui->checkBox_timer->setChecked(false); // 取消勾选
            return;
        }

        // 设置定时器间隔并启动
        timer->start(timeout);
    }
    else
    {
        // 停止定时器
        timer->stop();
        qDebug() << "定时发送停止";
    }
}


void MainWindow::timer_send_data()
{
    if (ui->comboBox_txformat->currentText() == "HEX")
    {
        this->tx_mode = 0;
        qDebug() << "hex模式";
    }
    else // 文本模式
    {
        this->tx_mode = 1;
        qDebug() << "文本模式";
    }

    if (my_Serial.isOpen())
    {
        if (this->tx_mode == 0) // hex发送
        {
            // 将用户输入的十六进制字符串转换为字节数组
            QByteArray data = QByteArray::fromHex(ui->textEdit_tx->toPlainText().toLatin1());
            this->tx_num += my_Serial.write(data);
        }
        else // 文本发送
        {
            // 直接发送用户输入的文本
            QByteArray data = ui->textEdit_tx->toPlainText().toLatin1();
            this->tx_num += my_Serial.write(data);
        }

        ui->label_tx_num->setText(QString::number(this->tx_num));
        qDebug() << "定时发送成功";
    }
    else
    {
        qDebug() << "串口未打开";
        ui->checkBox_timer->setChecked(false); // 取消勾选
    }
}

